@tool
class_name DeepSeekChat
extends Node

## 非流式DeepSeek生成内容节点

## deepseek Token，在开放平台获取
@export var secret_key: String = ''
## 深度思考
@export var use_thinking: bool = false
## 温度值，越高输出越随机，默认为1
@export_range(0.0, 2.0, 0.1) var temperature: float = 1.0
## 为正数时降低模型重复相同内容的可能性
@export_range(-2.0, 2.0, 0.1) var frequency_penalty: float = 0
## 为正数时增加模型谈论新主题的可能性
@export_range(-2.0, 2.0, 0.1) var presence_penalty: float = 0
## 最大输出长度，deepseek-chat模型，最大8K，deepseek-reasoner模型，最大64K
@export var max_tokens: int = 8192
## 输出内容的类型，如果为JSON，则必须在prompt中带有JSON字样，并带有示例
@export_enum("text", "json_object") var response_format: String = "text"

## 生成结束信号
signal generate_finish(msg: String, think_msg: String)

## 发送请求的HTTPRequest节点
var http_request: HTTPRequest = null
## 是否在生成中，可以使用此字段防止重复请求
var generatting: bool = false

func _ready() -> void:
	var node = HTTPRequest.new()
	add_child(node)
	http_request = node

## 发送请求
func post_message(messages: Array[Dictionary]):
	# 准备请求数据
	var headers = [
		"Accept: application/json",
		"Authorization: Bearer %s" % secret_key,
		"Content-Type: application/json"
	]

	var request_body = JSON.stringify({
		"messages": messages,
		"model": "deepseek-reasoner" if use_thinking else "deepseek-chat",
		"frequency_penalty": frequency_penalty,
		"max_tokens": max_tokens,
		"presence_penalty": presence_penalty,
		"response_format": {
			"type": response_format
		},
		"stream": false,
		"stream_options": null,
		"temperature": temperature,
		"top_p": 1,
		"tools": null,
		"tool_choice": "none",
		"logprobs": false,
		"top_logprobs": null
	})
	if not http_request.request_completed.is_connected(_http_request_completed):
		http_request.request_completed.connect(_http_request_completed)

	# 发送POST请求
	var err = http_request.request( "https://api.deepseek.com/chat/completions", headers, HTTPClient.METHOD_POST, request_body)
	generatting = true
	if err != OK:
		push_error("请求发送失败: " + str(err))
		return

func _http_request_completed(_result, _response_code, _headers, body: PackedByteArray):
	generatting = false
	var json = JSON.new()
	var err = json.parse(body.get_string_from_utf8())
	if err != OK:
		push_error("JSON解析错误: " + json.get_error_message())
		push_error(body.get_string_from_utf8())
		return

	var data = json.get_data()
	if data and data.has("choices"):
		var choices := data["choices"] as Array
		var think_msg = choices[0]["message"].get("reasoning_content", "")
		generate_finish.emit(choices[0]["message"]["content"], think_msg)
	else:
		print(data)
		push_error("无效的响应结构")

## 结束请求
func close():
	if http_request:
		http_request.cancel_request()
		generatting = false
